/** * personium.io * Copyright 2014 FUJITSU LIMITED * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.fujitsu.dc.core.bar; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.codehaus.jackson.JsonFactory; import org.codehaus.jackson.JsonParser; import org.codehaus.jackson.JsonToken; import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.map.exc.UnrecognizedPropertyException; import org.w3c.dom.Element; import com.fujitsu.dc.common.es.util.IndexNameEncoder; import com.fujitsu.dc.core.DcCoreException; import com.fujitsu.dc.core.auth.AccessContext; import com.fujitsu.dc.core.model.ctl.ExtRole; import com.fujitsu.dc.core.model.ctl.Relation; import com.fujitsu.dc.core.model.ctl.Role; /** * Httpリクエストボディからbarファイルを読み込むためのクラス. */ public class BarFileUtils { private static final int PATH_CELL_INDEX = 1; private static final int PATH_BOX_INDEX = 3; private BarFileUtils() { } /** * ACLの名前空間をバリデートする. * この際、ついでにロールインスタンスURLへの変換、BaseURLの変換を行う。 * @param entryName エントリ名 * @param element Elementノード * @param schemaUrl BoxスキーマURL * @return 処理結果 */ public static boolean aclNameSpaceValidate(final String entryName, final Element element, final String schemaUrl) { return true; } /** * 70_$links.jsonのFromName/ToNameに関する複合キーを取得する. * @param type FromType/ToNameに指定されたEntitySet名 * @param names FromName/ToNameに指定されたEntityKey名 * @param boxName Box名 * @return Entity作成時に使用するEntityKey名 */ public static String getComplexKeyName(final String type, final Map<String, String> names, final String boxName) { String keyname = null; // 複合キー if (type.equals(Role.EDM_TYPE_NAME) || type.equals(Relation.EDM_TYPE_NAME)) { keyname = String.format("(Name='%s',_Box.Name='%s')", names.get("Name"), boxName); // URI(ExtRole) } else if (type.equals(ExtRole.EDM_TYPE_NAME)) { keyname = String.format("(ExtRole='%s',_Relation.Name='%s',_Relation._Box.Name='%s')", names.get("ExtRole"), names.get("_Relation.Name"), boxName); // その他 } else { keyname = String.format("(Name='%s')", names.get("Name")); } return keyname; } /** * barファイル内に記載されたURLのホスト情報(scheme://hostname/)を処理中サーバの情報へ置換する. * @param url 変更対象のURL(エンコードされていないURL) * @param baseUrl インポート先のURL * @param fileName 処理中のbarファイルエントリ名 * @return 生成したURL */ public static String getLocalUrl(final String url, final String baseUrl, final String fileName) { String newUrl = baseUrl; if (newUrl.endsWith("/")) { newUrl = newUrl.substring(0, newUrl.length() - 1); } try { newUrl = newUrl + new URL(url).getPath(); } catch (MalformedURLException e) { throw DcCoreException.BarInstall.JSON_FILE_FORMAT_ERROR.params(fileName); } return newUrl; } /** * ACLの名前空間をバリデートする. * この際、ついでにロールインスタンスURLへの変換、BaseURLの変換を行う。 * @param element element * @param baseUrl baseUrl * @param cellName cellName * @param boxName boxName * @return 生成したElementノード */ public static Element convertToRoleInstanceUrl( final Element element, final String baseUrl, final String cellName, final String boxName) { String namespaceUri = element.getAttribute("xml:base"); String roleClassUrl = getLocalUrl(namespaceUri, baseUrl, BarFileReadRunner.ROOTPROPS_XML); Element retElement = (Element) element.cloneNode(true); String[] paths = null; try { URL url = new URL(roleClassUrl); paths = url.getPath().split("/"); } catch (MalformedURLException e) { throw DcCoreException.BarInstall.JSON_FILE_FORMAT_ERROR.params(BarFileReadRunner.ROOTPROPS_XML); } // ロールクラスURLからロールインスタンスURLへ変換して属性として設定 StringBuilder newBaseUrl = null; String url = baseUrl; if (url.endsWith("/")) { url = url.substring(0, url.lastIndexOf("/")); } newBaseUrl = new StringBuilder(url); paths[PATH_CELL_INDEX] = cellName; paths[PATH_BOX_INDEX] = boxName; for (String path : paths) { if (path.length() == 0) { continue; } newBaseUrl.append("/"); newBaseUrl.append(path); } newBaseUrl.append("/"); retElement.setAttribute("xml:base", newBaseUrl.toString()); return retElement; } /** * Cellオーナー情報からUnitUser名を取得する. * @param owner オーナー情報(URL) * @return UnitUser名 */ public static String getUnitUserName(final String owner) { String unitUserName = null; if (owner == null) { unitUserName = AccessContext.TYPE_ANONYMOUS; } else { unitUserName = IndexNameEncoder.encodeEsIndexName(owner); } return unitUserName; } /** * barファイルエントリからJSONファイルを読み込む. * @param <T> JSONMappedObject * @param inStream barファイルエントリのInputStream * @param entryName entryName * @param clazz clazz * @return JSONファイルから読み込んだオブジェクト * @throws IOException JSONファイル読み込みエラー */ public static <T> T readJsonEntry( InputStream inStream, String entryName, Class<T> clazz) throws IOException { JsonParser jp = null; ObjectMapper mapper = new ObjectMapper(); JsonFactory f = new JsonFactory(); jp = f.createJsonParser(inStream); JsonToken token = jp.nextToken(); // JSONルート要素("{") Pattern formatPattern = Pattern.compile(".*/+(.*)"); Matcher formatMatcher = formatPattern.matcher(entryName); String jsonName = formatMatcher.replaceAll("$1"); T json = null; if (token == JsonToken.START_OBJECT) { try { json = mapper.readValue(jp, clazz); } catch (UnrecognizedPropertyException ex) { throw DcCoreException.BarInstall.JSON_FILE_FORMAT_ERROR.params(jsonName); } } else { throw DcCoreException.BarInstall.JSON_FILE_FORMAT_ERROR.params(jsonName); } return json; } }